package com.codingfly.controller;

import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.digest.BCrypt;
import cn.hutool.crypto.symmetric.AES;
import com.codingfly.config.GlobalConfig;
import com.codingfly.controller.common.BaseController;
import com.codingfly.core.exception.BizException;
import com.codingfly.core.util.AssertUtils;
import com.codingfly.core.util.ResourcesUtils;
import com.codingfly.core.util.TokenUtils;
import com.codingfly.entity.SysUser;
import com.codingfly.model.dto.LoginDto;
import com.codingfly.model.Result;
import com.codingfly.model.dto.RegisterDto;
import com.codingfly.service.SysUserService;
import com.wf.captcha.GifCaptcha;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

@RestController
@RequestMapping("/oauth")
public class OauthController extends BaseController {
    private static Logger logger = LoggerFactory.getLogger(OauthController.class);
    private String sKey = "1234123412ABCDEF";//key，可自行修改，必须是16位。
    private String ivParameter = "ABCDEF1234123412";//偏移量,可自行修改
    private AES aesIV = new AES(Mode.CBC, Padding.PKCS5Padding, sKey.getBytes(), ivParameter.getBytes());

    @Autowired
    private SysUserService sysUserService;
    private Font font;

    @Value("${font.filepath:classpath:config/UbuntuMonoRegular.ttf}")
    private String fontFilePath;

    @PostConstruct
    public void init() throws IOException, FontFormatException {
        InputStream inputStream = ResourcesUtils.getInputStreamByPath(fontFilePath);
        font = Font.createFont(Font.TRUETYPE_FONT, inputStream);
        font = font.deriveFont(Font.PLAIN+Font.ITALIC+Font.BOLD, 33);
    }

    @PostMapping("/register")
    public Result register(@RequestBody RegisterDto register, HttpSession session) {
        checkParams(register, "code", "username", "password");
        String sessionId = session.getId();
        String code = GlobalConfig.sessionVerifyCode.getIfPresent(sessionId);
        GlobalConfig.sessionVerifyCode.invalidate(sessionId);
//        本地开发环境不校验token
//        AssertUtils.isTrue(register.getCode().equals(code), "验证码不正确");
        String username = null;
        String password = null;
        try {
            username = aesIV.decryptStr(register.getUsername());
            password = aesIV.decryptStr(register.getPassword());
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new BizException("非法参数");
        }
        if (sysUserService.findByUsername(username)!=null) {
            throw new BizException("该账号已注册");
        }
        SysUser sysUser = new SysUser();
        sysUser.setUsername(username);
        sysUser.setPassword(BCrypt.hashpw(password));
        sysUserService.save(sysUser);
        return Result.success();
    }

    @PostMapping("/login")
    public Result<String> login(@RequestBody LoginDto login, HttpSession session) {
        checkParams(login, "code", "username", "password");
        String sessionId = session.getId();
        String code = GlobalConfig.sessionVerifyCode.getIfPresent(sessionId);
        GlobalConfig.sessionVerifyCode.invalidate(sessionId);
//        本地开发环境不校验token
//        AssertUtils.isTrue(login.getCode().equals(code), "验证码不正确");
        String username = null;
        String password = null;
        try {
            username = aesIV.decryptStr(login.getUsername());
            password = aesIV.decryptStr(login.getPassword());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("账号/密码错误");
        }
        SysUser sysUser = sysUserService.findByUsername(username);
        if (sysUser==null || BCrypt.checkpw(password, sysUser.getPassword())==false) {
            throw new BizException("账号/密码错误");
        }
        String token = UUID.randomUUID().toString();
        GlobalConfig.tokenStorage.put(token, sysUser.getId());
        return Result.success(token);
    }

    @GetMapping("/verifyCode")
    public void verifyCode(HttpServletResponse response, HttpSession session) throws IOException {
        // 设置请求头为输出图片类型
        response.setContentType("image/gif");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0L);

        // 三个参数分别为宽、高、位数
        GifCaptcha gifCaptcha = new GifCaptcha(120, 40, 4);

        gifCaptcha.setFont(font);  // 有默认字体，可以不用设置
        String code = gifCaptcha.text().toLowerCase();
        logger.error(session.getId()+" 验证码 "+code);
        GlobalConfig.sessionVerifyCode.put(session.getId(), code);
        gifCaptcha.out(response.getOutputStream());
    }

    @GetMapping("/checkToken")
    public Result checkToken() {
        String accessToken = TokenUtils.getAccessTokenThrowErr();
        Integer userId = GlobalConfig.tokenStorage.getIfPresent(accessToken);
        return userId!=null? Result.success():Result.fail(401, "no Login");
    }

}
